﻿using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using TVersityDotNet.HelperTypes;
using System;
using System.Collections.ObjectModel;
using System.Globalization;

namespace TVersityDotNet.Responses
{
    public class DescriptionFetchResponse : TVersityResponse
    {
        public Description Description { get; set; }

        public DescriptionFetchResponse(XDocument responseXmlDoc)
        {
            this.ParseMessage(responseXmlDoc);                  
        }

        public override void ParseMessage(XDocument responseXml)
        {
            if (responseXml != null)
            {
                try
                {
                    IFormatProvider provider = CultureInfo.InvariantCulture;                   

                    string xmlNs = "urn:schemas-upnp-org:device-1-0";
                    XElement resultSet = responseXml.Element(XName.Get("root", xmlNs));
                    SpecVersion sv = new SpecVersion();
                    sv.Major = int.Parse(resultSet.Element(XName.Get("specVersion", xmlNs)).Element(XName.Get("major", xmlNs)).Value, provider);
                    sv.Minor = int.Parse(resultSet.Element(XName.Get("specVersion", xmlNs)).Element(XName.Get("minor", xmlNs)).Value, provider);

                    XElement deviceElement = resultSet.Element(XName.Get("device", xmlNs));

                    Device device = new Device();
                    device.DeviceType = deviceElement.Element(XName.Get("deviceType", xmlNs)).Value;
                    device.FriendlyName = deviceElement.Element(XName.Get("friendlyName", xmlNs)).Value;
                    device.Manufacturer = deviceElement.Element(XName.Get("manufacturer", xmlNs)).Value;
                    device.ManufacturerUrl = new Uri(deviceElement.Element(XName.Get("manufacturerURL", xmlNs)).Value);
                    device.ModelDescription = deviceElement.Element(XName.Get("modelDescription", xmlNs)).Value;
                    device.ModelName = deviceElement.Element(XName.Get("modelName", xmlNs)).Value;
                    device.ModelNumber = int.Parse(deviceElement.Element(XName.Get("modelNumber", xmlNs)).Value);
                    device.ModelUrl = new Uri(deviceElement.Element(XName.Get("modelURL", xmlNs)).Value);
                    device.SerialNumber = deviceElement.Element(XName.Get("serialNumber", xmlNs)).Value;
                    device.Upc = deviceElement.Element(XName.Get("UPC", xmlNs)).Value;
                    device.Udn = deviceElement.Element(XName.Get("UDN", xmlNs)).Value;
                    device.PresentationUrl = new Uri(deviceElement.Element(XName.Get("presentationURL", xmlNs)).Value);

                    Collection<TVIcon> icons = new Collection<TVIcon>();

                    var query = from result in deviceElement.Descendants(XName.Get("icon", xmlNs))
                                select new TVIcon
                                    (
                                        result.Element(XName.Get("mimetype", xmlNs)).Value,
                                        int.Parse(result.Element(XName.Get("width", xmlNs)).Value, CultureInfo.InvariantCulture),
                                        int.Parse(result.Element(XName.Get("height", xmlNs)).Value, CultureInfo.InvariantCulture),
                                        int.Parse(result.Element(XName.Get("depth", xmlNs)).Value, CultureInfo.InvariantCulture),
                                        new Uri(result.Element(XName.Get("url", xmlNs)).Value)
                                    );

                    foreach (TVIcon icon in query)
                    {
                        icons.Add(icon);
                    }

                    Collection<TVService> services = new Collection<TVService>();

                    var servicesQuery = from result in deviceElement.Descendants(XName.Get("service", xmlNs))
                                        select new TVService
                                            (
                                                result.Element(XName.Get("serviceType", xmlNs)).Value,
                                                result.Element(XName.Get("serviceId", xmlNs)).Value,
                                                new Uri(result.Element(XName.Get("SCPDURL", xmlNs)).Value),
                                                new Uri(result.Element(XName.Get("controlURL", xmlNs)).Value),
                                                new Uri(result.Element(XName.Get("eventSubURL", xmlNs)).Value)
                                            );

                    foreach (TVService service in servicesQuery)
                    {
                        services.Add(service);
                    }

                    Description = new Description(sv, device, icons, services);
                    this.ResponseSuccess = true;
                    this.ResponseMessage = "Retreival succeeded";
                }
                catch (Exception ex)
                {
                    this.ResponseSuccess = false;
                    this.ResponseMessage = "Retreival failed: " + ex.Message;
                }
            }
            else
            {
                this.ResponseSuccess = false;
                this.ResponseMessage = "Provided responseXml was null";
            }
        }
    }
}
